/*
 * Copyright 2013 JROSE
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.jrose.test.support;

import lombok.Getter;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.Resource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.jdbc.JdbcTestUtils;

import java.util.List;

/**
 * DDL script.
 *
 * @author Xiaohai Zhang
 * @since 2013-08-17 16:28
 */
@Slf4j
@RequiredArgsConstructor
public class DDLScript {
    @NonNull private final JdbcTemplate jdbcTemplate;

    @Getter @Setter private String tableName;
    @Getter @Setter private String script;
    @Getter @Setter private boolean upToDate = true;

    public void cleanup() {
        try {
            if (isUpToDate()) {
                cleanupTable();
                return;
            }

            String sql = "SELECT DDL_SCRIPT FROM DDL_SCRIPTS WHERE TABLE_NAME=?";
            List<String> scripts = jdbcTemplate.queryForList(sql, new Object[]{tableName}, String.class);
            if (scripts.isEmpty()) {
                // not found, do insert
                sql = "INSERT INTO DDL_SCRIPTS (TABLE_NAME,DDL_SCRIPT) VALUES (?,?)";
                jdbcTemplate.update(sql, tableName, script);
            } else {
                // do update
                sql = "UPDATE DDL_SCRIPTS SET DDL_SCRIPT=? WHERE TABLE_NAME=?";
                jdbcTemplate.update(sql, script, tableName);
            }

            rebuildTable();
        } catch (Exception ignored) {
            log.warn(ignored.getMessage(), ignored);
        }
    }

    private void cleanupTable() {
        try {
            String sql = "TRUNCATE TABLE " + tableName;
            jdbcTemplate.update(sql);
        } catch (Exception ex) {
            log.warn("Error occurs when truncating table " + tableName);
            rebuildTable();
        }
    }

    private void rebuildTable() {
        try {
            jdbcTemplate.update("DROP TABLE IF EXISTS " + tableName);
        } catch (Exception ignored) {
        }

        try {
            Resource resource = new ByteArrayResource(script.getBytes("UTF-8"));
            JdbcTestUtils.executeSqlScript(jdbcTemplate, resource, false);
        } catch (Exception ex) {
            throw new IllegalStateException(ex.getMessage(), ex);
        }
    }
}
